//
// Created by root on 2/23/18.
//

#include "oopengine.h"
#include "../premise/premise.h"
#include "../trans/matcher.h"
#include "../init/oop.h"

static ClassMeta *classMeta;

String defclass(Statement *s) {
    String className = extract_content(s);
    TreeNode *currentClassNode = tree_find(globalFunny->inheritance, className);
    return gen_defclass_code(currentClassNode);
}

String methodname(Statement *s) {
    String methodName = extract_content(s);
    String fullName = init_string();
    fullName = concatenate(fullName, classMeta->className);
    fullName = concatenate(fullName, "::");
    fullName = concatenate(fullName, methodName);
    return fullName;
}

String defmethod(Statement *s1, Statement *s2) {
    String method = extract_content(s1);
    Statement* definition = s2;
    String* strings = split_strings(method, "::");
    // String className = strings[0];
    String methodName = strings[1];
    MethodMeta *methodMeta;

    Queue * methods = classMeta->methods; //use className?
    QueueNode *node = NULL;
    if ((!is_queue_empty(methods))) {
        node = methods->head;
        while (node != NULL) {
            methodMeta = (MethodMeta *)(node->element);
            if (equals_string(methodName, methodMeta->methodName)) {
                methodMeta->methodDef = definition;
                break;
            }
            node = node->next;
        }
    }
    return NULL;
}

String newinstance(Statement *s1, Statement *s2) {
    String class = extract_content(s1);
    Statement* assignment = s2;
    TreeNode* classNode = tree_find(globalFunny->inheritance, class);

    Map map = hashmap_new();
    QueueNode *node = NULL;
    Statement* st1 = NULL;
    Statement* st2 = NULL;
    if ((!is_queue_empty(assignment->children))) {
        node = assignment->children->head;
        while (node != NULL) {
            st1 = (Statement *)(node->element);
            st2 = (Statement *)(node->next->element);
            hashmap_put(map, get_arg_name(st1), match_internal(st2));
            node = node->next->next;
        }
    }
    return gen_newinstance_code(classNode, map);
}

// (ask {object} {message} {args})
String sendmsg(Statement *s1, Statement *s2, Statement *s3) {
    String message = extract_content(s1);
    String messageArgs = join_from_queue(transform_queue(s2->children, extract_content), " ");
    String object = extract_content(s3);
    return gen_sendmsg_code(object, message, messageArgs);
}

// (if (is-null? {object}) () (ask {object} G-{prop}))
String getprop(Statement *s1, Statement *s2) {
    String property = extract_content(s1);
    String object = extract_content(s2);
    return gen_getprop_code(object, property);
}

// (if (is-null? {object}) () (ask {object} S-{prop} {value}))
String setprop(Statement *s1, Statement *s2, Statement *s3) {
    String property = extract_content(s1);
    String object = extract_content(s2);
    String value = match_internal(s3);
    return gen_setprop_code(object, property, value);
}
